<?php

namespace Yolo\ComponentManager;

use ReflectionException;
use Yolo\Di\Annotations\Singleton;
use Yolo\Di\DI;
use Yolo\Di\Errors\CircularDependencyException;
use Yolo\Di\Errors\InvalidAttributeException;
use Yolo\Di\Errors\ParameterTypeEmptyException;
use Yolo\Utils\Console;

#[Singleton]
class ComponentManager
{
    /**
     * @var AbstractComponent[] $components The components that have been registered.
     */
    protected array $components = [];

    /**
     * @param string $plugin
     * @return void
     * @throws ReflectionException
     * @throws CircularDependencyException
     * @throws ParameterTypeEmptyException|InvalidAttributeException
     */
    public function registerComponent(string $plugin): void
    {
        if (isset($this->components[$plugin])) return;

        $component = DI::use($plugin, false);
        if (!$component instanceof AbstractComponent) {
            Console::log("Component: $plugin is not a valid component, ignored.", 'error');
            return;
        }

        $component->register();

        $this->components[$plugin] = $component;

        Console::log("Component: Component $plugin registered.");
    }

    /**
     * Run after all components are registered.
     * @return void
     */
    public function runAfterRegistered(): void
    {
        foreach ($this->components as $component) {

            if (method_exists($component, 'registered')) {

                $component->registered();
            }
        }
    }

    /**
     * Check if a component is enabled.
     * @param string $component
     * @return bool
     */
    public function componentEnabled(string $component): bool
    {
        return isset($this->components[$component]);
    }

    /**
     * Get a registered component.
     * @param string $component Component class name
     * @return AbstractComponent|null
     */
    public function getRegisteredComponent(string $component): ?AbstractComponent
    {
        if (!$this->componentEnabled($component)) {
            return null;
        }

        return $this->components[$component];
    }
}
